﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI.WebControls;
using wne.models;
using wne.models.Filter;

namespace wne.core.Interface
{
    public abstract class AdminFacade
    {
        #region Groups
        

        /// <summary>
        /// Список полностью заполненных GroupSmallModel
        /// </summary>
        /// <param name="pFilter">Фильтр групп</param>
        /// <returns></returns>
        public abstract List<GroupSmallModel> GetFilteredGroupSmall(GroupSmallFilter pFilter);

        public abstract Dictionary<int, string> GetAllGroups(); 
        /// <summary>
        /// Допустимые родители для группы
        /// </summary>
        /// <param name="pIdGroup"></param>
        /// <returns>Ид и имя группы</returns>
        public abstract Dictionary<int, string> GetAvaliableParents(int pIdGroup);
        /// <summary>
        /// Дает заполненную группу с таким ид
        /// </summary>
        /// <param name="pId"></param>
        /// <returns></returns>
        public abstract GroupModel GetGroupById(int pId);
        /// <summary>
        /// удаляет родителя у группы
        /// </summary>
        /// <param name="pIdParent"></param>
        /// <param name="pIdGroup"></param>
        public abstract void DeleteParentForGroup(int pIdParent, int pIdGroup);
        /// <summary>
        /// добавить родителя к группе.
        /// Если нельзя добавить - кинуть эксепшн
        /// </summary>
        /// <param name="pIdParent"></param>
        /// <param name="pIdGroup"></param>
        public abstract void AddParentForGroup(int pIdParent, int pIdGroup);
        /// <summary>
        /// Обновляет группу в бд из модели
        /// </summary>
        /// <param name="pGroupModel"></param>
        public abstract void UpdateGroup(GroupModel pGroupModel);
        /// <summary>
        /// Грохнуть группу
        /// </summary>
        /// <param name="pId"></param>
        public abstract void RemoveGroup(int pId);
        /// <summary>
        /// Добавить группу, в ней заполнено только имя
        /// </summary>
        /// <param name="pGroupName"></param>
        /// <returns></returns>
        public abstract int AddGroup(string pGroupName);
        #endregion

        #region Users
        /// <summary>
        /// Отфильтрованный список пользователей
        /// </summary>
        /// <param name="pFilter">экземпляр фильтра</param>
        /// <returns></returns>
        public abstract List<UserModel> GetFilteredUsers(UserFilter pFilter);
        /// <summary>
        /// проставить - юзер pIdUser админ/неадмин
        /// </summary>
        /// <param name="pIdUser"></param>
        /// <param name="pIsAdmin"></param>
        public abstract void SetUserIsAdmin(int pIdUser, bool pIsAdmin);


        /// <summary>
        /// Группы, которым принадлежит пользователь, если нет в базе, возвращать пустой список
        /// </summary>
        /// <param name="pIdUser"></param>
        /// <returns></returns>
        public abstract Dictionary<int,string> GetGroupsByUser(int pIdUser);

        /// <summary>
        /// Возвращает модель пользователя, но только заполнены следующие поля: айди, логин, ФИО и список групп (айди и название).
        /// </summary>
        /// <param name="pIdUser">айди пользователя</param>
        /// <returns>-"-"-</returns>
        public abstract UserModel GetUserWithGroupsList(int pIdUser);


        /// <summary>
        /// Удалить группу у юзера вместе с заполненными полями от этой группы, 
        /// если нет юзера или нет у него такой группы - ничего не делать
        /// </summary>
        /// <param name="pIdUser"></param>
        /// <param name="pIdGroup"></param>
        public abstract void RemoveGroupFromUser(int pIdUser, int pIdGroup);
        /// <summary>
        /// Добавить группу юзеру, если нет юзера или группы - ничего не делать
        /// </summary>
        /// <param name="pIdUser"></param>
        /// <param name="pIdGroup"></param>
        public abstract void AddGroupToUser(int pIdUser, int pIdGroup);
        /// <summary>
        /// Дать юзера по ид, если нет такого юзера - вернуть созданный конструктором пустой объект UserModel
        /// с проинциализированными необходимыми полями (списки и прочие сложные объекты, чтобы не вылетал при обращении к ним)
        /// </summary>
        /// <param name="pUserId"></param>
        /// <returns></returns>
        public abstract UserModel GetUserById(int pUserId);
        //Id и UserGroups гарантированно пусты, их не добавляем
        /// <summary>
        /// Создает пользователя в базе данных. Возвращает (по-идее, вроде как) его айди.
        /// Должен работать при отсутствии групп у пользователя.
        /// </summary>
        /// <param name="pModel"></param>
        /// <returns></returns>
        public abstract int AddUser(UserModel pModel);
        /// <summary>
        /// Обновить пользователя из модели в бд. Должен НЕ СЛЕТАТЬ при отсутствии групп у пользователя, отсутствии полей в группе
        /// и других подобных ситуациях, когда цикл for идет по списку (массиву) который пуст. Проверять это! 
        /// </summary>
        /// <param name="pUserModel"></param>
        public abstract void UpdateUser(UserModel pUserModel);
        /// <summary>
        /// удалить пользователя
        /// </summary>
        /// <param name="pId"></param>
        public abstract void RemoveUser(int pId);
        /// <summary>
        /// Выдает список групп на добавление в них пользователя. То есть список тех групп,
        /// которым пользователь с переданным айди не принадлежит.
        /// </summary>
        /// <param name="pUserId">Айди пользоватлея, если нет такого - вернуть пустой проинициализированный список</param>
        /// <returns>int - айди группы в базе; string - название группы</returns>
        public abstract Dictionary<int, string> GetAvaliableGroupsForUser(int pUserId); 
        #endregion

        #region Routes

        /// <summary>
        /// Метод для создания в базе нового маршрута.
        /// Предусмотреть, что в входном объекте могут быть пустые списки и т.п., чтобы метод не слетал.
        /// </summary>
        /// <param name="pRouteModel">модель маршрута, в которой не забиты counter и WayId</param>
        /// <returns>0 - успех; 1 - какая-либо ошибка(пока что без конкретизации)</returns>
        public abstract int CreateRoute(RouteModel pRouteModel);
        
        /// <summary>
        /// Метод для обновления существующей в базе модели.
        /// Полностью переписывает существующую в базе модель с данным айди.
        /// Предусмотреть, что в входном объекте могут быть пустые списки и т.п., чтобы метод не слетал.
        /// </summary>
        /// <param name="pRouteModel">модель маршрута</param>
        /// <returns>0 - успех; 1 - нет такого маршрута (по айди) в базе; 2 - другая ошибка</returns>
        public abstract int UpdateRoute(RouteModel pRouteModel);
        
        /// <summary>
        /// Метод для удаления существующей в базе модели.
        /// Полностью удаляет из базы модель с переданным айди.
        /// </summary>
        /// <param name="pIdRoute">айди маршрута</param>
        /// <returns>0 - успех; 1 - нет маршрута с таким айди в базе; 2 - другая ошибка</returns>
        public abstract int DeleteRoute(int pIdRoute);
        
        /// <summary>
        /// Возвращает модель маршрута по переданному айди.
        /// Все списки и другие структуры должны быть проинициализированны.
        /// </summary>
        /// <param name="pIdRoute">айди модели</param>
        /// <returns>модель маршрута; при отсутсвии в базе такого маршрута в RouteId написать -2 (RouteId=-2).</returns>
        public abstract RouteModel GetRouteById(int pIdRoute);
        
        /// <summary>
        /// выдает список маршрутов для вывода на экран, отфильтрованный определенным образом.
        /// Точки (шаги) маршрута - не забивать.
        /// не забудьте, что сюда включается поиск по подстроке
        /// </summary>
        /// <param name="pFilter"></param>
        /// <returns>список моделей маршрута</returns>
        public abstract List<RouteModel> GetFilteredRoutes(RouteFilter_l pFilter);

        public abstract List<RouteModel> GetFilteredUsersRoutes(RouteFilter_l pFilter, int id);


        #endregion

       

        public virtual bool UserNotExists(string userName)
        {
            throw new NotImplementedException();
        }
        public virtual bool GroupNotExists(string userName)
        {
            throw new NotImplementedException();
        }
        public virtual bool RouteNotExists(string routeName)
        {
            throw new NotImplementedException();
        }
    }
}
